
from pydantic import BaseModel, Field, HttpUrl, EmailStr, UUID1
from typing import Literal, List, Annotated, Optional
from fastapi import FastAPI, Query, Path, Body, Cookie, Header, Response
import uvicorn

#输出列表的模型

app = FastAPI()

class FilterParams(BaseModel):
    # 限制额外的参数
    model_config = {"extra": "forbid"}
    # Field 用于对模型中的字段进行校验
    limit: int = Field(100, gt=0, le=100)
    offset: int = Field(0, ge=0)
    # Literal 表示字段的值必须是其中的某一个
    order_by: Literal["created_at", "updated_at"] = "created_at"
    # tags: list[str] = []
    tags: set[str] = set()

@app.post("/day02/pydantic_query")
def pydantic_query(query_parameter: FilterParams):
# def pydantic_query(query_parameter: FilterParams = Query()):
# def pydantic_query(query_parameter: Annotated[FilterParams, Query()]):
# def pydantic_query(query_parameter: FilterParams):
    return query_parameter



class CityInfo(BaseModel):
    name: str = Field(..., example="Beijing")  # example是注解的作用，值不会被验证
    country: str
    country_code: str = None  # 给一个默认值
    country_population: int = Field(default=800, title="人口数量", description="国家的人口数量", ge=800)

    class Config:
        schema_extra = {
            "example": {
                "name": "Shanghai",
                "country": "China",
                "country_code": "CN",
                "country_population": 1400000000,
            }
        }


@app.put("/request_body/city/{name}")
def mix_city_info(
    name: str,
    city01: CityInfo,
    city02: CityInfo,  # Body可以是多个的
    confirmed: int = Query(ge=0, description="确诊数", default=0),
    death: int = Query(ge=0, description="死亡数", default=0),
):
    if name == "Shanghai":
        return {"Shanghai": {"confirmed": confirmed, "death": death}}
    return city01.dict(), city02.dict()



class Image(BaseModel):
    url: HttpUrl
    name: str

'''
    模型的嵌套
'''
class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    email: EmailStr
    tax: Optional[float] = None
    tags: set[str] = set()
    # 子模型
    image: Optional[Image] = None


@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
    results = {"item_id": item_id, "item": item}
    return results

# 参数指定为一个列表
@app.post("/images/multiple/")
async def create_multiple_images(images: list[Image]):
    return images


@app.get("/set-cookie/")
async def set_cookie(response: Response):
    response.set_cookie(key="jesse_create_cookie", value="helloworld")
    return {"message": "Cookie 设置成功"}

# Cookie参数
@app.get("/cookie/")
def read_cookie(jesse_create_cookie: Annotated[Optional[str], Cookie()]):
    return jesse_create_cookie

@app.get("/header")
def header(user_agent: Optional[str] = Header(None, convert_underscores=True), x_token: List[str] = Header(None)):
    """
    有些HTTP代理和服务器是不允许在请求头中带有下划线的，所以Header提供convert_underscores属性让设置
    :param user_agent: convert_underscores=True 会把 user_agent 变成 user-agent
    :param x_token: x_token是包含多个值的列表
    :return:
    """
    print("User-Agent",user_agent)
    print("x_token",x_token)
    return {"User-Agent": user_agent, "x_token": x_token}





if __name__ == '__main__':
    uvicorn.run('day02:app', host='localhost', port=8001, reload=True)

